package hikari.hcomponents.physics;

import hikari.hcomponents.HComponent;
import hikari.objects3d.Basic3dObject;
import hikari.persistence.file.Chunk;
import hikari.persistence.file.FileSection;
import java.io.IOException;
import org.swig.jirr.vector3df;

/**
 * @author sad
 */
public class PhysicsData extends HComponent {

    private float mass = 1;
    private float restitution = 0;
    private float friction = 0.5f;
    private float rollingFriction = 0;
    private float ccdMotionThreshold = 0;
    private float contactProcessingThreshold = 99999999999999999999999999999999999999.f;
    private float ccdSweptRadius = 0;
    private float linearDamping = 0;
    private float angularDamping = 0;
    private float deactivationTime = 0;
    private float hitFraction = 1;
    private vector3df linearVelocity;
    private vector3df linearFactor;
    private vector3df angularFactor;
    private vector3df angularVelocity;
    private vector3df anisotropicFriction;
    private vector3df offsetPosition;
    private vector3df offsetRotation;
    private boolean disableDeactivation = false;
    private boolean kinematic = false;
    private boolean character = false;
    private boolean staticBody = true;
    private IRigidBody rigidBody;

    public PhysicsData() {
        linearVelocity = vector3df.NULLVECTOR;
        linearFactor = new vector3df(1, 1, 1);
        angularFactor = new vector3df(1, 1, 1);
        angularVelocity = vector3df.NULLVECTOR;
        anisotropicFriction = new vector3df(1, 1, 1);
        offsetPosition = vector3df.NULLVECTOR;
        offsetRotation = vector3df.NULLVECTOR;
    }

    public boolean isStaticBody() {
        return staticBody;
    }

    public void setStaticBody(boolean staticBody) {
        this.staticBody = staticBody;
    }
    
    

    public float getMass() {
        return mass;
    }

    public void setMass(float mass) {
        this.mass = mass;
    }

    public float getRestitution() {
        return restitution;
    }

    public void setRestitution(float restitution) {
        this.restitution = restitution;
    }

    public float getFriction() {
        return friction;
    }

    public void setFriction(float friction) {
        this.friction = friction;
    }

    public float getRollingFriction() {
        return rollingFriction;
    }

    public void setRollingFriction(float rollingFriction) {
        this.rollingFriction = rollingFriction;
    }

    public vector3df getLinearFactor() {
        return linearFactor;
    }

    public void setLinearFactor(vector3df linearFactor) {
        this.linearFactor = linearFactor;
    }

    public vector3df getAngularFactor() {
        return angularFactor;
    }

    public void setAngularFactor(vector3df angularFactor) {
        this.angularFactor = angularFactor;
    }

    public float getCcdMotionThreshold() {
        return ccdMotionThreshold;
    }

    public void setCcdMotionThreshold(float ccdMotionThreshold) {
        this.ccdMotionThreshold = ccdMotionThreshold;
    }

    public float getContactProcessingThreshold() {
        return contactProcessingThreshold;
    }

    public void setContactProcessingThreshold(float contactProcessingThreshold) {
        this.contactProcessingThreshold = contactProcessingThreshold;
    }

    public float getCcdSweptRadius() {
        return ccdSweptRadius;
    }

    public void setCcdSweptRadius(float ccdSweptRadius) {
        this.ccdSweptRadius = ccdSweptRadius;
    }

    public float getLinearDamping() {
        return linearDamping;
    }

    public void setLinearDamping(float linearDamping) {
        this.linearDamping = linearDamping;
    }

    public float getAngularDamping() {
        return angularDamping;
    }

    public void setAngularDamping(float angularDamping) {
        this.angularDamping = angularDamping;
    }

    public float getDeactivationTime() {
        return deactivationTime;
    }

    public void setDeactivationTime(float deactivationTime) {
        this.deactivationTime = deactivationTime;
    }

    public float getHitFraction() {
        return hitFraction;
    }

    public void setHitFraction(float hitFraction) {
        this.hitFraction = hitFraction;
    }

    public vector3df getLinearVelocity() {
        return linearVelocity;
    }

    public void setLinearVelocity(vector3df linearVelocity) {
        this.linearVelocity = linearVelocity;
    }

    public vector3df getAngularVelocity() {
        return angularVelocity;
    }

    public void setAngularVelocity(vector3df angularVelocity) {
        this.angularVelocity = angularVelocity;
    }

    public vector3df getAnisotropicFriction() {
        return anisotropicFriction;
    }

    public void setAnisotropicFriction(vector3df anisotropicFriction) {
        this.anisotropicFriction = anisotropicFriction;
    }

    public vector3df getOffsetPosition() {
        return offsetPosition;
    }

    public void setOffsetPosition(vector3df offsetPosition) {
        this.offsetPosition = offsetPosition;
    }

    public vector3df getOffsetRotation() {
        return offsetRotation;
    }

    public void setOffsetRotation(vector3df offsetRotation) {
        this.offsetRotation = offsetRotation;
    }

    public boolean isDisableDeactivation() {
        return disableDeactivation;
    }

    public void setDisableDeactivation(boolean disableDeactivation) {
        this.disableDeactivation = disableDeactivation;
    }

    public boolean isKinematic() {
        return kinematic;
    }

    public void setKinematic(boolean kinematic) {
        this.kinematic = kinematic;
    }

    public boolean isCharacter() {
        return character;
    }

    public void setCharacter(boolean character) {
        this.character = character;
    }

    public IRigidBody getRigidBody() {
        return rigidBody;
    }

    public void setRigidBody(IRigidBody rigidBody) {
        this.rigidBody = rigidBody;
    }

    @Override
    public void writeData(FileSection section) throws IOException {
        super.writeData(section);
        FileSection s = section.createNewSection("bulletPhys");
        s.writeFloat("mass", getMass());
        s.writeFloat("restitut", getRestitution());
        s.writeFloat("frict", getFriction());
        s.writeFloat("rollingFrict", getRollingFriction());
        s.writeFloat("motThres", getCcdMotionThreshold());
        s.writeFloat("contProcThr", getContactProcessingThreshold());
        s.writeFloat("sweptradius", getCcdSweptRadius());
        s.writeFloat("linearDamp", getLinearDamping());
        s.writeFloat("angDamp", getAngularDamping());
        s.writeFloat("deactTime", getDeactivationTime());
        s.writeFloat("hitfract", getHitFraction());
        s.writeVector("linearVelocity", getLinearVelocity());
        s.writeVector("linearFactor", getLinearFactor());
        s.writeVector("angularFactor", getAngularFactor());
        s.writeVector("angularVelocity", getAngularVelocity());
        s.writeVector("anisFriction", getAnisotropicFriction());
        s.writeVector("offsetPos", getOffsetPosition());
        s.writeVector("offsetRot", getOffsetRotation());
        s.writeBoolean("disableDeact", isDisableDeactivation());
        s.writeBoolean("isChar", isCharacter());
        s.writeBoolean("isKinemat", isKinematic());
        s.writeBoolean("isStatic", isStaticBody());
        FileSection rigidBodySection = s.createNewSection("rigidBody");
        rigidBody.write(rigidBodySection);
        rigidBodySection.close();
        s.close();
    }

    @Override
    public void loadData(FileSection section, Basic3dObject object) throws IOException {
        super.loadData(section, object); //To change body of generated methods, choose Tools | Templates.
        setMass(section.readFloat("mass"));
        setRestitution(section.readFloat("restitut"));
        setFriction(section.readFloat("frict"));
        setRollingFriction(section.readFloat("rollingFrict"));
        setCcdMotionThreshold(section.readFloat("motThres"));
        setContactProcessingThreshold(section.readFloat("contProcThr"));
        setCcdSweptRadius(section.readFloat("sweptradius"));
        setLinearDamping(section.readFloat("linearDamp"));
        setAngularDamping(section.readFloat("angDamp"));
        setDeactivationTime(section.readFloat("deactTime"));
        setHitFraction(section.readFloat("hitfract"));
        setLinearVelocity(section.readVector("linearVelocity"));
        setLinearFactor(section.readVector("linearFactor"));
        setAngularFactor(section.readVector("angularFactor"));
        setAngularVelocity(section.readVector("angularVelocity"));
        setAnisotropicFriction(section.readVector("anisFriction"));
        setOffsetPosition(section.readVector("offsetPos"));
        setOffsetRotation(section.readVector("offsetRot"));
        setDisableDeactivation(section.readBoolean("disableDeact"));
        setCharacter(section.readBoolean("isChar"));
        setKinematic(section.readBoolean("isKinemat"));
        setStaticBody(section.readBoolean("isStatic"));
        loadRigidBody(section.readSection("rigidBody"), object);
    }

    private void loadRigidBody(FileSection section, Basic3dObject object) throws IOException {
        for (Chunk chunk : section.getAllSections()) {
            FileSection rigidSection = section.readSection(chunk);
            IRigidBody tRigidBody = null;
            switch (chunk.getName()) {
                case "boxRigid":
                    tRigidBody = new BoxRigidBody(object.getMeshSceneNode(), this);
                    tRigidBody.read(rigidSection);
                    break;
                case "sphereRigid":
                    tRigidBody = new SphereRigidBody(object.getMeshSceneNode(), this);
                    tRigidBody.read(rigidSection);
                    break;
                case "cylinderRigid":
                    tRigidBody = new CylinderRigidBody(object.getMeshSceneNode(), this);
                    tRigidBody.read(rigidSection);
                    break;
                case "trimeshRigid":
                    tRigidBody = new TrimeshRigidBody(object.getMeshSceneNode(), this);
                    tRigidBody.read(rigidSection);
                    break;
                case "convexHullRigid":
                    tRigidBody = new ConvexHullRigidBody(object.getMeshSceneNode(), this);
                    tRigidBody.read(rigidSection);
                    break;
                default:
                    throw new RuntimeException("Not found handler for rigid body [" + chunk.getName() + "]");
            }
            setRigidBody(tRigidBody);
        }
    }
}
